package com.xiaochong.bitong.job.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xc.logclient.utils.LogTrace;
import com.xiaochong.bitong.job.component.RedisCacheComponent;
import com.xiaochong.bitong.job.config.hbase.HbaseBaseQueryComponent;
import com.xiaochong.bitong.job.util.StringUtil;
import com.xiaochong.service.common.config.oss.OSSTool;
import com.xiaochong.service.common.config.redis.RedisServer;
import com.xiaochong.tir.common.data.hbasepo.DiagnosisScore;
import com.xiaochong.tir.common.data.hbasepo.TradesHistory;
import com.xiaochong.tir.common.data.hbasepo.TradesHistoryCountFive;
import com.xiaochong.tir.common.data.hbasepo.TradesToKLine;
import com.xiaochong.tir.common.data.mapper.CurrencyInfoMapper;
import com.xiaochong.tir.common.data.mapper.ExchangeTransactionpairMiddleMapper;
import com.xiaochong.tir.common.data.mapper.KLineMapper;
import com.xiaochong.tir.common.data.mapper.PurchaseOrderMapper;
import com.xiaochong.tir.common.data.po.CurrencyInfo;
import com.xiaochong.tir.common.data.po.ExchangeTransactionpairMiddle;
import com.xiaochong.tir.common.data.po.KLine;
import com.xiaochong.tir.common.data.po.PurchaseOrder;
import com.xiaochong.tir.common.data.redisPo.CoinPriceVo;
import com.xiaochong.tir.common.data.redisPo.KActionTotalPo;
import com.xiaochong.tir.common.data.vo.*;
import com.xiaochong.tir.common.exception.hbase.HbaseCloseExcetion;
import com.xiaochong.tir.common.exception.hbase.HbaseConnectionExcetion;
import com.xiaochong.tir.common.exception.hbase.HbaseGetTableExcetion;
import com.xiaochong.tir.common.util.*;
import net.sf.json.util.JSONTokener;
import org.apache.commons.lang3.StringUtils;
import org.apache.hadoop.hbase.filter.Filter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.time.LocalDateTime;
import java.util.*;

/**
 * Created by Administrator on 2018/8/14.
 */
@Service
public class CurrencyService {
    @Autowired
    HbaseBaseQueryComponent hbaseBaseQueryComponent;

    @Autowired
    private RedisCacheComponent redisCacheComponent;

    @Autowired
    private ExchangeTransactionpairMiddleMapper exchangeTransactionpairMiddleMapper;

    @Autowired
    private RedisServer redisServer;

    @Autowired
    private CurrencyInfoMapper currencyInfoMapper;

    @Autowired
    private OssImageUtil ossImageUtil;

    @Autowired
    private OSSTool ossTool;

    @Autowired
    private KLineMapper kLineMapper;

    @Autowired
    private PurchaseOrderMapper purchaseOrderMapper;

    /**
     * K线(列表)
     * @param rowKey
     * @return
     * @throws HbaseConnectionExcetion
     * @throws HbaseGetTableExcetion
     * @throws IOException
     * @throws HbaseCloseExcetion
     */
    private String getBroaderData(String rowKey) throws HbaseConnectionExcetion, HbaseGetTableExcetion, IOException, HbaseCloseExcetion {
        String grailStr = hbaseBaseQueryComponent.selectByQualifierData(HbaseTableUtils.API_SERVICE_K_ACTION_TABLE_NAME
                , HbaseTableUtils.API_SERVICE_K_ACTION_TABLE_NAME_FAMILY
                , HbaseTableUtils.API_SERVICE_K_ACTION_QUALIFIER
                , rowKey
        );
        LogTrace.info("hbase货币查询","是否存在数据"+rowKey, StringUtils.isBlank(grailStr)?"无数据":"有数据");
        return grailStr;
    }

    /**
     * cmc货币信息表查询
     * @param rowKey
     * @return
     * @throws HbaseConnectionExcetion
     * @throws HbaseGetTableExcetion
     * @throws IOException
     * @throws HbaseCloseExcetion
     */
    private CurrencyDataVo getBroaderDataByCmc(String cmcId,int daySize,int hourSize,int kSize,int hourInter) throws HbaseConnectionExcetion, HbaseGetTableExcetion, IOException, HbaseCloseExcetion {
        String nowDateHoursStr = DateUtils.dateFormatString(new Date(),DateUtils.format_ymdh_x);
        String hourStr = nowDateHoursStr.substring(nowDateHoursStr.length()-2,nowDateHoursStr.length());
        int hourStrInt = Integer.valueOf(hourStr);
        CurrencyDataVo currencyDataVo = new CurrencyDataVo();
        List<String> x=new ArrayList<>(  );
        List<String> y=new ArrayList<>(  );
        for (int j=0;j<daySize;j++){
            String rowkey = DateUtils.getNextDayDateYMD(-j);//取rowkey
            String  grailStr = hbaseBaseQueryComponent.selectByQualifierData(HbaseTableUtils.DAILY_CURRENCY_INFOR_TABLE_NAME
                    , HbaseTableUtils.DAILY_CURRENCY_INFOR_TABLE_FAMILY
                    , HbaseTableUtils.DAILY_CURRENCY_INFOR_TABLE_QUALIFIER
                    , cmcId+"@"+rowkey
            );

            for (int i = 0; i < hourSize; i++) {
                JSONObject json = JSON.parseObject( grailStr );
                int nowHour = hourStrInt;
                if(hourStrInt == 0){
                    hourStrInt = 23;
                }else{
                    hourStrInt--;
                }
                JSONArray advice = null;

                if (json != null) {
                    advice = (JSONArray) json.getJSONArray( nowHour + "" );
                }
                if (advice != null) {
                    for ( int k = advice.size()-1; k >=0; k--) {
                        JSONObject obj = (JSONObject) advice.get( k );
                        if (obj.containsKey("createTime")) x.add( obj.getString("createTime")); //货币价格Cny
                        if (obj.containsKey("priceCny")) y.add( String.valueOf( getConverCut( obj.getString("priceCny") ))); //货币价格Cny
                        k=k-kSize;
                    }
                }
                if(hourInter==1){
                    break;
                }
            }
        }

        Collections.reverse( x );
        Collections.reverse( y );
        currencyDataVo.setX( x );
        currencyDataVo.setY( y );
        return currencyDataVo;
    }

    /**
     * 货币数据图表
     * @return
     * @throws HbaseCloseExcetion
     * @throws IOException
     * @throws HbaseGetTableExcetion
     * @throws HbaseConnectionExcetion
     */
    public CurrencyDataVo getCurrencyOfTime(int id,int interval,long time,String cmcId,int daySize,int hourSize,int kSize,int hourInter) throws HbaseCloseExcetion, IOException, HbaseGetTableExcetion, HbaseConnectionExcetion {
        CurrencyDataVo vo=new CurrencyDataVo();
        Long nowTImeres = new Date(  ).getTime();

        ExchangeTransactionpairMiddle exchangeTransactionpairMiddle = new ExchangeTransactionpairMiddle();
        exchangeTransactionpairMiddle.setCurrencyId( id );
        List<ExchangeTransactionpairMiddle>  ExchangeTransactionpairMiddleList=exchangeTransactionpairMiddleMapper.selectByEntityList( exchangeTransactionpairMiddle );
        List<String> x=new ArrayList<>(  );
        List<String> y=new ArrayList<>(  );
        long d=0;
        boolean flag=false;
        if(ExchangeTransactionpairMiddleList.size()>0){
            while (true){
                long now=nowTImeres-d;
                LocalDateTime timeres = DateUtils.getDateTimeOfTimestamp(now);
                String lastRowKey = DateUtils.localDateTimeFormatString(timeres,DateUtils.format_ymdhm);//当前时间转成分钟
                double price=0;
                int size=ExchangeTransactionpairMiddleList.size();
                for(int i=0;i<ExchangeTransactionpairMiddleList.size();i++){
                    exchangeTransactionpairMiddle=ExchangeTransactionpairMiddleList.get( i );
                    String rowKey = exchangeTransactionpairMiddle.getExchangeId()+"@"+exchangeTransactionpairMiddle.getTransactionName()+"@"+lastRowKey;
                    String grailStr = getBroaderData(rowKey);
                    TradesToKLine tradesToKLine=new TradesToKLine();
                    if(StringUtils.isBlank( grailStr ) && StringUtils.isBlank( tradesToKLine.getPriceCny() ) ){
                        size-=1;
                    }else{
                        flag=true;
                        Object listArray = new JSONTokener(grailStr).nextValue();
                        if(listArray instanceof  net.sf.json.JSONArray){//老数据兼容问题
                            JSONArray jsonArray = JSON.parseArray(grailStr);
                            tradesToKLine = new TradesToKLine();
                            tradesToKLine.setTimestamp(jsonArray.getString(0));
                            tradesToKLine.setOpenPrice(jsonArray.getString(1));
                            tradesToKLine.setHighestPrice(jsonArray.getString(2));
                            tradesToKLine.setLowestPrice(jsonArray.getString(3));
                            tradesToKLine.setClosePrice(jsonArray.getString(4));
                            tradesToKLine.setVolume(jsonArray.getString(5));
                        }else{
                            tradesToKLine = JSON.parseObject( grailStr,TradesToKLine.class );
                        }
                    }
                    if(StringUtils.isNotBlank( tradesToKLine.getPriceCny() )){
                        price=price+Double.parseDouble( tradesToKLine.getPriceCny()  );
                    }
                }
                if(flag==true){
                    x.add(now+"");
                    y.add( getConverCut( String.valueOf( price/size ) )+"" );
                    flag=false;
                }
                size+=1;
                d+=interval;
                if(d>=time){
                    break;
                }
            }
            Collections.reverse(x);
            Collections.reverse(y);
            vo.setX( x );
            vo.setY( y );
        }else{
            vo=getBroaderDataByCmc( cmcId,daySize,hourSize,kSize,hourInter );
        }

        return vo;
    }




    public ApiResultVo<TradesHistoryData> capitalFlowDistribution24H(String cmcId) throws HbaseCloseExcetion, IOException, HbaseGetTableExcetion, HbaseConnectionExcetion {
        ApiResultVo apiResultVo = new ApiResultVo();
        apiResultVo.setTradeId(LogTrace.getTrace().getTraceId());

        try{
            CurrencyInfo info = redisCacheComponent.getCurrencyInfo(cmcId);
            ExchangeTransactionpairMiddle exchangeTransactionpairMiddle = new ExchangeTransactionpairMiddle();
            exchangeTransactionpairMiddle.setCurrencyId( info.getId() );
            List<ExchangeTransactionpairMiddle>  ExchangeTransactionpairMiddleList=exchangeTransactionpairMiddleMapper.selectByEntityList( exchangeTransactionpairMiddle );

            LocalDateTime time = LocalDateTime.now();
            time = time.minusMinutes(10);//当前分钟不要，可能为插入到hbase中
            String timePart=null;
            BigDecimal base = new BigDecimal( 100 );

            BigDecimal allInflux = new BigDecimal( 0 ); //总流入
            BigDecimal mainInflux = new BigDecimal( 0 ); //主力流入
            BigDecimal mainFlowOutflow = new BigDecimal( 0 ); //主力流出
            BigDecimal mainNetInflow = new BigDecimal( 0 ); //主力净流入

            BigDecimal allFlow = new BigDecimal( 0 ); //总流出
            BigDecimal retailInflow = new BigDecimal( 0 ); //散户流入
            BigDecimal retailOutflow = new BigDecimal( 0 ); //散户流出
            BigDecimal netInflowOfRetailInvestors = new BigDecimal( 0 ); //散户净流入

            BigDecimal flow24h = new BigDecimal( 0 ); //24小时净流入

            for(int i=0;i<288;i++){
                //循环288次，共24小时,5分钟一条
                int minu = time.getMinute()/5;
                timePart = DateUtils.localDateTimeFormatString(time,DateUtils.format_ymdh);
                timePart += minu < 10 ? "0"+minu:minu;

                for(int k=0;k<ExchangeTransactionpairMiddleList.size();k++){
                    exchangeTransactionpairMiddle = ExchangeTransactionpairMiddleList.get( k );
                    int exchangeId=exchangeTransactionpairMiddle.getExchangeId();
                    String transactionName = exchangeTransactionpairMiddle.getTransactionName();
                    String rowKey = HbaseTableUtils.API_SERVICE_TRADES_PART__ROWKEY + "@" + exchangeId + "@" + transactionName + "@" + timePart;
                    String tradesHistory =  getCapitalInflowSituation(rowKey);
                    if(tradesHistory!=null){
                        TradesHistoryCountFive historyCountFive = JSON.parseObject(tradesHistory,TradesHistoryCountFive.class);
                        allInflux=allInflux.add( historyCountFive.getBuyAmount() );
                        allFlow=allFlow.add( historyCountFive.getSellAmount());
                    }
                }
                time = time.minusMinutes( 5 );
            }

            for(int i=0;i<ExchangeTransactionpairMiddleList.size();i++){
                exchangeTransactionpairMiddle = ExchangeTransactionpairMiddleList.get( i );
                PurchaseOrder purchaseOrder = new PurchaseOrder();
                purchaseOrder.setExchangeId( exchangeTransactionpairMiddle.getExchangeId() );
                purchaseOrder.setTransactionPair( exchangeTransactionpairMiddle.getTransactionName() );
                purchaseOrder.setTimeStamp( new Date(  ).getTime()-86400000 +"");
                List<PurchaseOrder> purchaseOrderList = purchaseOrderMapper.getPurchaseOrderListByExId(purchaseOrder);
                for(int j=0;j<purchaseOrderList.size();j++){
                    PurchaseOrder purchaseOrder1 = purchaseOrderList.get( j );
                    int exchangeId = purchaseOrder1.getExchangeId();
                    String sys=purchaseOrder1.getTransactionPair();
                    TradesHistory tradesHistory=new TradesHistory();
                    tradesHistory.setPrice( new BigDecimal( purchaseOrder1.getPrice()) );
                    tradesHistory.setNewPriceCny( new BigDecimal( purchaseOrder1.getPrice()) );
                    tradesHistory = conversionPrice(exchangeId,sys,tradesHistory);
                    if(purchaseOrder1.getDealSign().equals( "0" )){
                        //买的
                        mainInflux=mainInflux.add(tradesHistory.getNewPriceCny().multiply( new BigDecimal( purchaseOrder1.getCount() ) ) );
                    }else{
                        //卖的
                        mainFlowOutflow=mainFlowOutflow.add(tradesHistory.getNewPriceCny().multiply( new BigDecimal( purchaseOrder1.getCount() ) ) );
                    }
                }
            }

            retailInflow=allInflux.subtract( mainInflux );
            retailOutflow=allFlow.subtract( mainFlowOutflow );
            mainNetInflow=mainInflux.subtract( mainFlowOutflow );
            netInflowOfRetailInvestors=retailInflow.subtract( retailOutflow );
            flow24h=allInflux.subtract( allFlow );

            mainNetInflow=mainInflux.subtract( mainFlowOutflow );
            netInflowOfRetailInvestors=retailInflow.subtract( retailOutflow );
            TradesHistoryData tradesHistoryData = new TradesHistoryData();
            tradesHistoryData.setMainInflux( String.valueOf( mainInflux.setScale(2,BigDecimal.ROUND_DOWN) )  );
            tradesHistoryData.setMainFlowOutflow(String.valueOf( mainFlowOutflow.setScale(2,BigDecimal.ROUND_DOWN) ));
            tradesHistoryData.setMainNetInflow(String.valueOf( mainNetInflow.setScale(2,BigDecimal.ROUND_DOWN) ));
            tradesHistoryData.setRetailInflow(String.valueOf( retailInflow.setScale(2,BigDecimal.ROUND_DOWN) ));
            tradesHistoryData.setRetailOutflow(String.valueOf( retailOutflow.setScale(2,BigDecimal.ROUND_DOWN) ));
            tradesHistoryData.setNetInflowOfRetailInvestors(String.valueOf( netInflowOfRetailInvestors.setScale(2,BigDecimal.ROUND_DOWN) ));

            BigDecimal sum = mainInflux.add( mainFlowOutflow ).add( retailInflow ).add( retailOutflow ); //总和
            MathContext mc = new MathContext(6, RoundingMode.HALF_DOWN);
            //占比计算
            if(!sum.equals( BigDecimal.ZERO )){
                tradesHistoryData.setMainInfluxRatio( String.valueOf( mainInflux.divide( sum, mc).multiply( base ).stripTrailingZeros() ) );
                tradesHistoryData.setMainFlowOutflowRatio( String.valueOf( mainFlowOutflow.divide( sum,mc ).multiply( base ).stripTrailingZeros() ) );
                tradesHistoryData.setRetailInflowRatio( String.valueOf( retailInflow.divide( sum,mc ).multiply( base ).stripTrailingZeros() ) );
                tradesHistoryData.setRetailOutflowRatio( String.valueOf( retailOutflow.divide( sum,mc ).multiply( base ).stripTrailingZeros() ) );
            }
            redisServer.set( RedisKeyApp.FLOW_INDEX+cmcId, flow24h.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue() );
            apiResultVo.setData( tradesHistoryData );
        }catch (Exception e){
            e.printStackTrace();
            LogTrace.error("24H资金流向分布",e);
            return  apiResultVo;
        }
        return apiResultVo;
    }


    private String getCapitalInflowSituation(String rowKey) throws HbaseConnectionExcetion, HbaseGetTableExcetion, IOException, HbaseCloseExcetion {
        String tradesHistory =  hbaseBaseQueryComponent.selectByQualifierData( HbaseTableUtils.API_SERVICE_TRADES_TABLE_NAME
                , HbaseTableUtils.API_SERVICE_TRADES_TABLE_NAME_FAMILY
                , HbaseTableUtils.API_SERVICE_TRADES_QUALIFIER
                , rowKey
        );
        return tradesHistory;
    }


    private TradesHistory conversionPrice(Integer exchangeId, String symbol, TradesHistory tradesHistory) {
        String [] sy = symbol.split("/");
        //美元获取汇率
        String rmbUsd = redisServer.get(RedisKeysUtils.RMB_USD_RATE);

        BigDecimal rmbUsdToCny = new BigDecimal(rmbUsd);
        String baseCoin = sy[1];
        baseCoin = baseCoin.toUpperCase();
        if(!"CNY".equals(baseCoin)){
            if(!"USD".equals(baseCoin) && !"USDT".equals(baseCoin)){  //查找到对应的usdt或者usd价格
                String[] searchCoin = {baseCoin+"/USDT",baseCoin+"/USD"};
                LocalDateTime time = LocalDateTime.now();
                int i = 0;
                String converPrice = "";
                Integer exchangeIdConvert = redisServer.get(RedisKeyApp.EXCHANGE_PING_TAI_B_CONVERT+exchangeId,Integer.class);
                if(exchangeIdConvert != null){
                    exchangeId =exchangeIdConvert;
                }
                for(String coin :searchCoin){
                    //  String redisPriceDate = DateUtils.localDateTimeFormatString(time,DateUtils.format_ymds);
                    String changeRedisKey = RedisKeysUtils.API_SERVICE_K_ACTION_ALL_DATA_PRICE+"@"+exchangeId+"@"+coin;
                    String data = redisServer.get(changeRedisKey);
                    KActionTotalPo kActionTotalPo = JSON.parseObject(data,KActionTotalPo.class);
                    if(kActionTotalPo != null){
                        converPrice = kActionTotalPo.getLastOpenPrice();
                        break;
                    }
                }
                if(StringUtils.isNotBlank(converPrice)){
                    BigDecimal conPrice = new BigDecimal(converPrice);
                    tradesHistory.setNewPriceCny(tradesHistory.getPrice().multiply(conPrice));
                    tradesHistory.setNewPriceUsd(tradesHistory.getPrice().multiply(conPrice));
                    tradesHistory.setPingPrice(conPrice);
                }
            }else{
                tradesHistory.setNewPriceCny(tradesHistory.getPrice());
                tradesHistory.setNewPriceUsd(tradesHistory.getPrice());
            }
            tradesHistory.setRmbUsdt(rmbUsdToCny);
            tradesHistory.setNewPriceCny(tradesHistory.getNewPriceCny()!=null?tradesHistory.getNewPriceCny().multiply(rmbUsdToCny):tradesHistory.getPrice().multiply(rmbUsdToCny));
        }
        return tradesHistory;
    }


    public ApiResultVo<TradesHistoryData> capitalStatistics(String cmcId) throws HbaseCloseExcetion, IOException, HbaseGetTableExcetion, HbaseConnectionExcetion {
        ApiResultVo apiResultVo = new ApiResultVo();
        apiResultVo.setTradeId(LogTrace.getTrace().getTraceId());

        try{
            //7日涨幅计算
            double change7Day=0;
            String INDUSTRY_INDEX=redisServer.get( RedisKeyApp.CYRRENCY_INDEX+7+":"+24+":"+cmcId );
            if (org.apache.commons.lang.StringUtils.isNotBlank( INDUSTRY_INDEX )) {
                List<CurrencyDataVo> CurrencyDataVoList = JSON.parseArray( INDUSTRY_INDEX, CurrencyDataVo.class );
                if(CurrencyDataVoList.size()>0){
                    CurrencyDataVo currencyDataVo = CurrencyDataVoList.get( 0 );
                    List<String> x = currencyDataVo.getX();
                    List<String> y = currencyDataVo.getY();
                    if(x.size()>0 && y.size()>0 && Double.parseDouble(y.get( 0 ))>0){
                        change7Day=( Double.parseDouble(y.get( y.size()-1 ))-Double.parseDouble(y.get( 0 ) ) )/Double.parseDouble(y.get( 0 ))*100;
                    }
                }
            }

            apiResultVo.setData(StringUtil.getDoubleTwo( change7Day ));
        }catch (Exception e){
            e.printStackTrace();
            LogTrace.error("7日涨幅计算",e);
        }
        return apiResultVo;
    }


    public void getCurrencyQuotation() {
        ApiResultVo resultVo = new ApiResultVo();
        try {
            List<CurrencyQuotationResultVo> quotationList = new ArrayList<>();

            try {
                CurrencyInfo currencyInfo = new CurrencyInfo();
                currencyInfo.setEnableFlag( true );
                currencyInfo.setDeleteFlag( false );
                List<CurrencyInfo> currencyList = currencyInfoMapper.selectByEntityList( currencyInfo );

                for (int i = 0; i < currencyList.size(); i++) {
                    CurrencyInfo info = currencyList.get( i );
                    if (!org.apache.commons.lang.StringUtils.isEmpty( info.getCmcId() )) {
                        CurrencyQuotationResultVo currencyQuotationResultVo = setCurrencyCatch( info.getCmcId() );
                        if(currencyQuotationResultVo == null){
                            LogTrace.info("getCurrencyQuotation"  , "货币数据为空" , info.getCmcId());
                            continue;
                        }
                        //最新价格
                        ExchangeTransactionpairMiddle exchangeTransactionpairMiddle = new ExchangeTransactionpairMiddle();
                        exchangeTransactionpairMiddle.setCurrencyId( Integer.valueOf( currencyQuotationResultVo.getId() ) );
                        List<ExchangeTransactionpairMiddle>  ExchangeTransactionpairMiddleList=exchangeTransactionpairMiddleMapper.selectByEntityList( exchangeTransactionpairMiddle );
                        if(ExchangeTransactionpairMiddleList.size()>0){
                            CoinPriceVo coinPriceVo = getNewPrice( currencyQuotationResultVo.getCmcId() );
                            if (currencyQuotationResultVo != null && coinPriceVo!=null) {
                                if (org.apache.commons.lang.StringUtils.isNotBlank( coinPriceVo.getPriceCny() )) {
                                    currencyQuotationResultVo.setPriceCny( getConverCut( ( coinPriceVo.getPriceCny() )).doubleValue() );
                                    currencyQuotationResultVo.setLastOpenPrice(getConverCut( coinPriceVo.getPriceUsd())+"" );
                                }
                                if (coinPriceVo.getChang24h() != null) {
                                    currencyQuotationResultVo.setChange24h( Double.parseDouble( coinPriceVo.getChang24h() ) );
                                }
                            }
                        }
                        quotationList.add( currencyQuotationResultVo );
                    }
                }
                redisServer.set( RedisKeyApp.CURRENCY_LIST_APP,JSON.toJSONString( quotationList) );
            } catch (Exception e) {
                e.printStackTrace();
                LogTrace.error( "货币行情", e );
            }
        } catch (Exception e) {
            e.printStackTrace();
            LogTrace.error( "货币行情", e );
            resultVo.setTradeId( LogTrace.getTrace().getTraceId() );
        }
    }

    public CurrencyQuotationResultVo getCurrencyByCmcId(String cmcId) {
        if(org.apache.commons.lang.StringUtils.isEmpty(cmcId)){ return null;}
        /**
         * 实时的交易所数据
         */
        return getCurrencyByCmcIdAndUserToken(cmcId);
    }


    /**
     * 根据cmcid
     * @param cmcId
     * @return
     */
    public CurrencyQuotationResultVo getCurrencyByCmcIdAndUserToken(String cmcId) {
        if(org.apache.commons.lang.StringUtils.isEmpty(cmcId)) return null;

        String redisCacheKey =  RedisKeysUtils.CURRENCY_MARKET+cmcId;

        String result=redisServer.get( redisCacheKey);
        CurrencyQuotationResultVo currencyQuotationResultVo=new CurrencyQuotationResultVo();
        if (result!=null){
            currencyQuotationResultVo = JSON.parseObject( result,CurrencyQuotationResultVo.class );
            return currencyQuotationResultVo;
        }else{
            try {
                if(StringUtils.isNotBlank( cmcId )){
                    currencyQuotationResultVo = setCurrencyCatch(cmcId);
                    return currencyQuotationResultVo;
                }
            } catch (Exception e) {
                e.printStackTrace();
                LogTrace.error( "根据cmcid", e );
            }
        }
        return null;
    }

    public CoinPriceVo getNewPrice(String cmcId){
        String priceRedisKey = RedisKeyApp.COIN_PRICE+cmcId;
        String priceRedisData = redisServer.get(priceRedisKey);
        if(org.apache.commons.lang.StringUtils.isNotBlank(priceRedisData)) {
            CoinPriceVo coinPriceVoOld = JSON.parseObject( priceRedisData, CoinPriceVo.class );
            return coinPriceVoOld;
        }
        return  null;
    }


    /**
     * 根据cmsId获取 货币信息
     * @param cmsId
     * @return
     */
    public CurrencyInfo getCurrencyInfo(String cmsId){
        String currencyInfo = redisServer.hashGet(RedisKeysUtils.CURRENCY_INFO_KEY,cmsId);
        if(org.apache.commons.lang3.StringUtils.isNotBlank(currencyInfo)){
            return JSONObject.parseObject(currencyInfo,CurrencyInfo.class);
        }
        currencyInit();
        return currencyInfoMapper.selectByEntity(new CurrencyInfo().setCmcId(cmsId));

    }

    /**
     * 货币缓存 初始化
     */
    public void currencyInit(){
        List<CurrencyInfo> currencyInfoList = currencyInfoMapper.selectByEntityList(new CurrencyInfo().setDeleteFlag(false).setEnableFlag(true));
        currencyInfoList.forEach(currencyInfo -> {
            currencyInfo.setImageUrl(ossImageUtil.fmtImg(currencyInfo.getImageUrl()));
            if(currencyInfo.getWeights()){
                redisServer.hashSet(RedisKeysUtils.CURRENCY_WEIGHTS_KEY,currencyInfo.getCmcId(),JSONObject.toJSONString(currencyInfo));
            }
            redisServer.hashSet(RedisKeysUtils.CURRENCY_INFO_KEY,currencyInfo.getCmcId(), JSONObject.toJSONString(currencyInfo));
        });
    }

    public CurrencyQuotationResultVo setCurrencyCatch(String cmcId) {
        if(org.apache.commons.lang.StringUtils.isEmpty(cmcId)){ return null;}

        /**
         * 实时的交易所数据
         */
        String redisCacheKey =  RedisKeysUtils.CURRENCY_MARKET+cmcId;

        /**
         * 5分钟的CMC数据
         */
        String redisCacheKeyCmc =  RedisKeysUtils.CURRENCY_MARKET+"@"+cmcId;

        String result=redisServer.get( redisCacheKeyCmc);
        if (org.apache.commons.lang.StringUtils.isNotBlank(result) && redisServer.exists(redisCacheKeyCmc)){
            LogTrace.info("getCurrencyByCmcId@cmc" , "resultKey" , redisCacheKeyCmc );
            CurrencyQuotationResultVo currencyQuotationResultVo = JSON.parseObject( result,CurrencyQuotationResultVo.class );
            //最新价格
            ExchangeTransactionpairMiddle exchangeTransactionpairMiddle=new ExchangeTransactionpairMiddle();
            exchangeTransactionpairMiddle.setTransactionName(cmcId);
            List<ExchangeTransactionpairMiddle> exchangeTransactionpairMiddleList = exchangeTransactionpairMiddleMapper.getTransactionPairByCurrencyInfo( exchangeTransactionpairMiddle );
            if(exchangeTransactionpairMiddleList.size()>0){
                exchangeTransactionpairMiddle = exchangeTransactionpairMiddleList.get( 0 );
                String Rediskey = RedisKeysUtils.API_SERVICE_K_ACTION_ALL_DATA_PRICE + "@" + exchangeTransactionpairMiddle.getExchangeId()+ "@" + exchangeTransactionpairMiddle.getTransactionName();
                String API_SERVICE_K_ACTION_CHANGE_PRICE = redisServer.get( Rediskey );
                if(API_SERVICE_K_ACTION_CHANGE_PRICE!=null){
                    KActionTotalPo rActionTotalPo = JSON.parseObject( API_SERVICE_K_ACTION_CHANGE_PRICE,KActionTotalPo.class );
                    currencyQuotationResultVo.setPriceCny( rActionTotalPo.getOpenPriceCny()!=null? getConverCut(rActionTotalPo.getOpenPriceCny()).doubleValue():0);
                    currencyQuotationResultVo.setChangFlag(rActionTotalPo.getChangFlag()!=null?rActionTotalPo.getChangFlag():0);
                    //今日涨幅
                    currencyQuotationResultVo.setTodayGains( rActionTotalPo.getChangePrice()!=null?Double.parseDouble( rActionTotalPo.getChangePrice() ):0.00);

                    //差值计算
                    double difference=currencyQuotationResultVo.getPriceCny()*currencyQuotationResultVo.getTodayGains();
                    currencyQuotationResultVo.setDifference(getDoubleTwo( difference/100 ));
                }
            }
            redisServer.set( redisCacheKey,JSON.toJSONString( currencyQuotationResultVo ));
            return currencyQuotationResultVo;
        }

        try {
            CurrencyQuotationResultVo currencyQuotationResultVo=new CurrencyQuotationResultVo();
            CurrencyQuotationResultVo currencyQuotationResultVo2=new CurrencyQuotationResultVo();
            CurrencyInfo info = getCurrencyInfo( cmcId );
            currencyQuotationResultVo.setName( info.getSymbol()+"-"+info.getCoinNameCn() );
            currencyQuotationResultVo.setCmcId( info.getCmcId() );
            currencyQuotationResultVo.setSymbol(info.getSymbol());
            currencyQuotationResultVo.setCoinNameCn( info.getCoinNameCn() );
            currencyQuotationResultVo.setCoinNameEn( info.getCoinNameEn() );
            if(info.getImageUrl()!=null){
                if(info.getImageUrl().contains( "http" )){
                    currencyQuotationResultVo.setImageUrl( info.getImageUrl() );
                }else{
                    String imgUrl = ossTool.getOSSUrl( info.getImageUrl() );
                    currencyQuotationResultVo.setImageUrl( imgUrl );
                }
            }
            currencyQuotationResultVo.setId( info.getId().toString() );

            int d=0;
            String grailStr =null;

            String rowKey = cmcId + "@" +DateUtils.getNextDayDateYMD(-d);
            LogTrace.info("getCurrencyByCmcId" , "hbaseBaseQueryComponent-begin" , rowKey);

            grailStr = hbaseBaseQueryComponent.selectByQualifierData(HbaseTableUtils.DAILY_CURRENCY_INFOR_TABLE_NAME
                    , HbaseTableUtils.DAILY_CURRENCY_INFOR_TABLE_FAMILY
                    , HbaseTableUtils.DAILY_CURRENCY_INFOR_TABLE_QUALIFIER
                    , rowKey
            );
            if (grailStr!=null){
                JSONObject json = JSON.parseObject( grailStr );
                JSONArray adviceFirst = null;
                JSONArray advice = null;
                if (json != null) {
                    Set<String> setString=json.keySet();
                    int firstKey=24;
                    int lastKey=0;
                    for (String str : setString) {
                        int minStr=Integer.valueOf( str );
                        if (minStr<firstKey){
                            firstKey=minStr;
                        }
                    }
                    for (String str : setString) {
                        int maxStr=Integer.valueOf( str );
                        if (maxStr>lastKey){
                            lastKey=maxStr;
                        }
                    }
                    adviceFirst = (JSONArray) json.getJSONArray( firstKey+"" );
                    advice = (JSONArray) json.getJSONArray( lastKey+"" );
                }

                if (adviceFirst!=null){
                    JSONObject obj=adviceFirst.getJSONObject( 0 );
                    if (obj.containsKey("priceCny")) currencyQuotationResultVo2.setPriceCny( getConverCut(  obj.getString("priceCny")  ).doubleValue() ); //货币价格
                }

                if (advice!=null){
                    JSONObject obj=advice.getJSONObject( advice.size()-1 );
                    if (obj.containsKey("marketCapCny"))currencyQuotationResultVo.setMarketCapCny(RetainCount( Double.parseDouble(obj.get("marketCapCny")+""),2 ));  //流通市值
                    if (obj.containsKey("circulation24hCny")) currencyQuotationResultVo.setCirculatingSupply(RetainCount( Double.parseDouble( obj.get("circulation24hCny").toString()),0 ));   //流通数量
                    if (obj.containsKey("volume24hCny")) currencyQuotationResultVo.setVolume24h(RetainCount( Double.parseDouble(obj.get("volume24hCny")+""),0 ));//成交额
                    if (obj.containsKey("percentChange24h")) currencyQuotationResultVo.setChange24h(RetainCount( Double.parseDouble(obj.get("percentChange24h")+""),2 )); //24小时涨幅
                    if (obj.containsKey("percentChange1h")) currencyQuotationResultVo.setChange1h(RetainCount( Double.parseDouble(obj.get("percentChange1h")+""),2 )); //1小时涨幅
                    if (obj.containsKey("rank")) currencyQuotationResultVo.setMarkRank(obj.get("rank").toString()); //流通市值排名字段
                    if (obj.containsKey("priceCny")) currencyQuotationResultVo.setPriceCny( getConverCut(  obj.getString("priceCny")  ).doubleValue() ); //货币价格
                    if (currencyQuotationResultVo2.getPriceCny()!=null&&currencyQuotationResultVo2.getPriceCny()>0) currencyQuotationResultVo.setTodayGains( StringUtil.getDoubleTwo( ( currencyQuotationResultVo.getPriceCny()-currencyQuotationResultVo2.getPriceCny() )/currencyQuotationResultVo2.getPriceCny()*100 ) ); //今日涨幅
                    currencyQuotationResultVo.setDifference( StringUtil.getDoubleTwo( currencyQuotationResultVo.getPriceCny()*currencyQuotationResultVo.getTodayGains()/100 ) ); //差值
                    if (obj.containsKey("priceUsd")) currencyQuotationResultVo.setLastOpenPrice( String.valueOf( getConverCut(  obj.getString("priceUsd") ) ) ); //货币价格Usd
                    String CMC_PRICE_CHANGFLAG = redisServer.get(RedisKeysUtils.CMC_PRICE_CHANGFLAG+cmcId);
                    if(org.apache.commons.lang.StringUtils.isNotBlank( CMC_PRICE_CHANGFLAG )){
                        double priceCnyLast=Double.valueOf( CMC_PRICE_CHANGFLAG );
                        if(currencyQuotationResultVo.getPriceCny()>priceCnyLast){
                            currencyQuotationResultVo.setChangFlag( 1 );
                        }else if(currencyQuotationResultVo.getPriceCny()==priceCnyLast){
                            currencyQuotationResultVo.setChangFlag( 0 );
                        }else{
                            currencyQuotationResultVo.setChangFlag( -1 );
                        }
                    }
                    redisServer.set( RedisKeysUtils.CMC_PRICE_CHANGFLAG+cmcId,currencyQuotationResultVo.getPriceCny() );
                }
            }

            ApiCurrencyDiagnosisScoreVo scoreVo=new ApiCurrencyDiagnosisScoreVo();
            String redisDate = redisServer.get(RedisKeysUtils.DIAGNOSIS_CURRENCY_SCORE_INFO+cmcId);
            if (org.apache.commons.lang.StringUtils.isNotBlank( redisDate )){
                scoreVo = JSON.parseObject(redisDate,ApiCurrencyDiagnosisScoreVo.class);
            }else {
                scoreVo = MakeCurrencyDiagnosisScore(cmcId);
            }
            if (scoreVo!=null){
                currencyQuotationResultVo.setScore(Double.parseDouble(scoreVo.getScore()));
            }
            //换手率
            if(currencyQuotationResultVo.getMarketCapCny() != null &&
                    currencyQuotationResultVo.getMarketCapCny()!=0
                    &&
                    currencyQuotationResultVo.getVolume24h()!=null
                    &&
                    currencyQuotationResultVo.getMarketCapCny()!=null){
                currencyQuotationResultVo.setTurnover(getDoubleTwo((currencyQuotationResultVo.getVolume24h()/currencyQuotationResultVo.getMarketCapCny()*100)));
            }

            ExchangeTransactionpairMiddle exchangeTransactionpairMiddle=new ExchangeTransactionpairMiddle();
            exchangeTransactionpairMiddle.setTransactionName(cmcId);
            List<ExchangeTransactionpairMiddle> exchangeTransactionpairMiddleList = exchangeTransactionpairMiddleMapper.getTransactionPairByCurrencyInfo( exchangeTransactionpairMiddle );
            if(exchangeTransactionpairMiddleList.size()>0){
                exchangeTransactionpairMiddle = exchangeTransactionpairMiddleList.get( 0 );
                //7日k线图
                List<KLine> KLine7D=new ArrayList<>(  );
                for (int i=0;i<7;i++){
                    KLine kLine=new KLine();
                    kLine.setExchangeId( exchangeTransactionpairMiddle.getExchangeId() );
                    kLine.setTransationPairName(  exchangeTransactionpairMiddle.getTransactionName());
                    kLine.setKDate( DateUtils.getNextDayDateYMD2(-i) );
                    List<KLine> kList = kLineMapper.selectKline8h( kLine );
                    KLine7D.addAll( kList );
                }
                currencyQuotationResultVo.setKLine7D( KLine7D );

                //最新价格
                String Rediskey = RedisKeysUtils.API_SERVICE_K_ACTION_ALL_DATA_PRICE + "@" + exchangeTransactionpairMiddle.getExchangeId()+ "@" + exchangeTransactionpairMiddle.getTransactionName();
                String API_SERVICE_K_ACTION_CHANGE_PRICE = redisServer.get( Rediskey );
                if(API_SERVICE_K_ACTION_CHANGE_PRICE!=null){
                    KActionTotalPo rActionTotalPo = JSON.parseObject( API_SERVICE_K_ACTION_CHANGE_PRICE,KActionTotalPo.class );
                    currencyQuotationResultVo.setPriceCny( rActionTotalPo.getOpenPriceCny()!=null? getConverCut(rActionTotalPo.getOpenPriceCny()).doubleValue():0);
                    currencyQuotationResultVo.setChangFlag(rActionTotalPo.getChangFlag()!=null?rActionTotalPo.getChangFlag():0);
                    //今日涨幅
                    currencyQuotationResultVo.setTodayGains( rActionTotalPo.getChangePrice()!=null?Double.parseDouble( rActionTotalPo.getChangePrice() ):0.00);

                    //差值计算
                    double difference=currencyQuotationResultVo.getPriceCny()*currencyQuotationResultVo.getTodayGains();
                    currencyQuotationResultVo.setDifference(getDoubleTwo( difference/100 ));
                }
                //交易对名称
                currencyQuotationResultVo.setTransactionName( exchangeTransactionpairMiddle.getTransactionName() );
            }

            if(currencyQuotationResultVo.getMarketCapCny()==null) {
                currencyQuotationResultVo.setMarketCapCny(0.00);
            }
            if(currencyQuotationResultVo.getChange24h()==null) {
                currencyQuotationResultVo.setChange24h(0.00);
            }
            if(currencyQuotationResultVo.getChange1h()==null) {
                currencyQuotationResultVo.setChange1h(0.00);
            }
            if(currencyQuotationResultVo.getCirculatingSupply()==null) {
                currencyQuotationResultVo.setCirculatingSupply( 0.00 );
            }
            if(currencyQuotationResultVo.getVolume24h()==null) {
                currencyQuotationResultVo.setVolume24h( 0.00 );
            }
            if(currencyQuotationResultVo.getScore()==null) {
                currencyQuotationResultVo.setScore( 0.00 );
            }
            if(currencyQuotationResultVo.getPriceCny()==null) {
                currencyQuotationResultVo.setPriceCny( 0.00 );
            }
            if(currencyQuotationResultVo.getLastOpenPrice()==null){
                currencyQuotationResultVo.setLastOpenPrice( 0+"" );
            }
            String highPriceKey =  RedisKeysUtils.TIR_CMC_HIGH_PRICE+cmcId;
            String lowPriceKey =  RedisKeysUtils.TIR_CMC_LOW_PRICE+cmcId;
            String highPrice = redisServer.get(highPriceKey);
            String lowPrice = redisServer.get(lowPriceKey);

            currencyQuotationResultVo.setHighPrice( highPrice );
            currencyQuotationResultVo.setLowPrice( lowPrice );

            redisServer.set( redisCacheKeyCmc,JSON.toJSONString( currencyQuotationResultVo ) , 300L);
            return currencyQuotationResultVo;
        }catch (Exception e){
            e.printStackTrace();
            LogTrace.error("币种详情",e);
        }
        return null;
    }

    //保留小数点后几位小数
    public static Double RetainCount (Double f,int count){
        BigDecimal bigDecimal = new BigDecimal(f);
        //这里的 2 就是你要保留几位小数。
        double f1 = bigDecimal.setScale(count, BigDecimal.ROUND_HALF_UP).doubleValue();
        return f1;
    }

    /**
     * 组装货币诊断得分到redis中
     * @param cmc_id
     * @throws Exception
     */
    public ApiCurrencyDiagnosisScoreVo MakeCurrencyDiagnosisScore(String cmc_id) throws Exception{
        ApiCurrencyDiagnosisScoreVo vo=new ApiCurrencyDiagnosisScoreVo();
        String grailStr = null;
        //获取当前小时
        String rowKey = "";
        int day =0;
        while (org.apache.commons.lang.StringUtils.isBlank(grailStr)){//循环获取，指导获取到数据
            rowKey = DateUtils.getNextDayDateYMD(day);
            grailStr = hbaseBaseQueryComponent.selectByQualifierData(HbaseTableUtils.CURRENCY_DIAGNOSIS_SCORE_TABLE_NAME
                    , HbaseTableUtils.CURRENCY_DIAGNOSIS_SCORE_TABLE_FAMILY
                    , HbaseTableUtils.CURRENCY_DIAGNOSIS_SCORE_QUALIFIER
                    , cmc_id+"@"+rowKey);//DateUtils.getCurrentDateString()
            day --;
            if(org.apache.commons.lang.StringUtils.isNotBlank(grailStr)||day<-1){
                break;
            }
        }
        LogTrace.info("hbase数据查询",rowKey+"是否存在数据"+cmc_id, org.apache.commons.lang.StringUtils.isBlank(grailStr)?"无数据":"有数据");
        if(org.apache.commons.lang3.StringUtils.isBlank(grailStr)){
            return null;
        }
        //数据库查询模型symbol
        CurrencyInfo queryInfo = new CurrencyInfo();
        queryInfo.setCmcId(cmc_id);
        Long dstart = System.currentTimeMillis();
        // CurrencyInfo infoList  =  currencyInfoMapper.selectByEntity(queryInfo);
        CurrencyInfo info = getCurrencyInfo(cmc_id);
        LogTrace.info("量化评估-获取诊断得分-redis查询","耗时",String.valueOf(System.currentTimeMillis()-dstart));
        //获取指定货币量能变化  DiagnosisQuantumEnergy
        Map<String,Object> diagnosisMap = JSON.parseObject(grailStr);
        String dataDiagnosi = "";
        int maxHour = 0;
        //获取最后数据
        for(Map.Entry<String,Object> maxMap : diagnosisMap.entrySet()){
            int tempHour = Integer.valueOf(maxMap.getKey());
            if(tempHour >= maxHour){
                maxHour = tempHour;
                //dataDiagnosi = JSON.toJSONString(diagnosisMap.get(String.valueOf(hourStr)));
                dataDiagnosi = JSON.toJSONString(maxMap.getValue());
            }
        }
        LogTrace.info("量化评估-获取诊断得分-时间",String.valueOf(maxHour), org.apache.commons.lang.StringUtils.isBlank(dataDiagnosi)?"无数据":"有数据");
        List<DiagnosisScore> diagnosisScoreList = JSON.parseArray(dataDiagnosi,DiagnosisScore.class);
        if(diagnosisScoreList == null || diagnosisScoreList.size() == 0) return null;
        DiagnosisScore diagnosisScore = diagnosisScoreList.get(diagnosisScoreList.size()-1);
        vo.setDiagnosisId(String.valueOf(1));
        vo.setScore(diagnosisScore.getDiagnosisScore().setScale(1, BigDecimal.ROUND_DOWN).toString());
        //记录内容是否为空
        LogTrace.info("量化评估-获取诊断得分-量能、流动、市场、ar人气数据","数据",JSON.toJSONString(diagnosisScore));
        //评语
        vo.setEnergyChange(diagnosisScore.getQuantumEnergyComment()!=null?diagnosisScore.getQuantumEnergyComment():"");
        vo.setCurrencyLiquidity(diagnosisScore.getLiquidityComment()!=null?diagnosisScore.getLiquidityComment():"");
        vo.setPopularityIndex(diagnosisScore.getPopularityIndicatorComment()!=null?diagnosisScore.getPopularityIndicatorComment():"");
        vo.setMarketHeat(diagnosisScore.getTrendsInfoResult()!=null && diagnosisScore.getTrendsInfoResult()!=null?diagnosisScore.getTrendsInfoResult():""); //市场热度评语
        vo.setWinPercent(diagnosisScore.getDefect()!=null?diagnosisScore.getDefect().multiply(BigDecimal.valueOf(100)).setScale(2,BigDecimal.ROUND_DOWN).toString():"0");  //打败
        //雷达图数据插入顺序 市场热度，人气指标，货币流动性，量能变化
        List<String> indicator = new ArrayList<>();
        indicator.add(diagnosisScore.getTrendsInfoScore()!=null&&diagnosisScore.getTrendsInfoScore()!=null?diagnosisScore.getTrendsInfoScore().toString():"0");//市场待取
        indicator.add(diagnosisScore.getPopularityIndicatorScore()!=null?diagnosisScore.getPopularityIndicatorScore().toString():"0");//ar人气指标
        indicator.add(diagnosisScore.getLiquidityScore()!=null?diagnosisScore.getLiquidityScore().toString():"0"); //货币流动性
        indicator.add(diagnosisScore.getQuantumEnergyScore()!=null?diagnosisScore.getQuantumEnergyScore().toString():"0");//量能变化
        vo.setIndicator(indicator);
        if(info!=null){
            vo.setSymbol(info.getSymbol());//插入模型
            vo.setCoinNameCn(info.getCoinNameCn());
            if(info.getImageUrl()!=null){
                if(info.getImageUrl().contains( "http" )){
                    vo.setImageUrl( info.getImageUrl() );
                }else{
                    String imgUrl = ossTool.getOSSUrl( info.getImageUrl() );
                    vo.setImageUrl( imgUrl );
                }
            }
        }

        redisServer.set(RedisKeysUtils.DIAGNOSIS_CURRENCY_SCORE_INFO+cmc_id,JSON.toJSONString(vo),300L);
        return  vo;
    }

    //保留小数点后两位位
    public static Double getDoubleTwo(Double dou){
        String b=String.format("%.2f", dou);
        Double c=Double.parseDouble(b);
        return c;
    }

    public static BigDecimal getConverCut(String lastPriceB) {
        BigDecimal result = new BigDecimal(0);
        result = org.apache.commons.lang3.StringUtils.isNotBlank(lastPriceB)?new BigDecimal(lastPriceB).setScale(10,BigDecimal.ROUND_DOWN):result;
        if(result.compareTo(BigDecimal.valueOf(1)) >=0){
            result = result.setScale(2,BigDecimal.ROUND_DOWN);
        }else{
            BigDecimal divisor = BigDecimal.ONE;
            MathContext mc = new MathContext(5);
            result = result.divide(divisor, mc);
        }
        return result;
    }

}
